#pragma once
#include <iostream>
#include <string>
#include <cstring>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <memory>
#include"log.hpp"
#include "inetAdder.hpp"
//使用模板方法来实现（设计模式）
namespace socketmodule
{
    using namespace logmodule;
    int defaultbacklog = 128;
    class Socket//套接字虚基类
    {
        public:
        virtual ~Socket(){}
        virtual void Socketing() = 0;//创建套接字过程
        virtual void binding(uint16_t port) = 0;//绑定过程
        virtual void listening(int backlog) = 0;//监听过程
        virtual std::shared_ptr<Socket> accepting(inetaddr *client) = 0;//连接过程
        virtual void close() = 0;
        virtual int Recv(std::string *out) = 0;
        virtual int Send(std::string &out) = 0;
        virtual int Connecting(uint16_t port,std::string ip) = 0;
        public:
        void BuildTcpsocket(uint16_t port,int backlog = defaultbacklog)
        {
            Socketing();
            binding(port);
            listening(backlog);
        }

        void buildTcpclientsocket()
        {
            Socketing();

        }
        // void BuildUdpsocket()
        // {
        //     Socketing();
        //     binding();
        // }
    };
    const static int defaultsockfd = -1;
    class Tcpsocket:public Socket
    {
        public:
        Tcpsocket(int sockfd):_sockfd(sockfd)
        {}
        Tcpsocket():_sockfd(defaultsockfd)
        {}
        Tcpsocket(const std::string ip,uint16_t port)
        {}
        ~Tcpsocket(){}
        virtual void Socketing() override//创建套接字过程
        {
            _sockfd = ::socket(AF_INET,SOCK_STREAM,0);
            if(_sockfd<0)
            {
                LOG(loglevel::FATAL)<<"socketing error";
                exit(1);
            }
            LOG(loglevel::INFO)<<"socketing success";
        }
        virtual void binding(uint16_t port)//绑定过程
        {
            inetaddr local(port);
            int n  = ::bind(_sockfd,local.Netaddrptr(),local.Netaddrlen());
            if(n<0)
            {
                LOG(loglevel::FATAL)<<"binding error";
                exit(2);
            }
            LOG(loglevel::INFO)<<"binding success";

        }
        virtual void listening(int backlog)//监听过程
        {
            int n = ::listen(_sockfd,backlog);
             if(n<0)
            {
                LOG(loglevel::FATAL)<<"listening error";
                exit(2);
            }
            LOG(loglevel::INFO)<<"listening success";
        }
        virtual std::shared_ptr<Socket> accepting(inetaddr *client)//连接过程,一个输出型参数
        {
            struct sockaddr_in peer;
            socklen_t len = sizeof(peer);
            int fd = ::accept(_sockfd,CONV(peer),&len);//链接套接字
            if(fd<0)
            {
                LOG(loglevel::FATAL)<<"accepting error";
                return nullptr;
            }
            client->SetAddr(peer);
            return std::make_shared<Tcpsocket>(fd);//?
        }
        void close()
        {
            if(_sockfd>=0)
            ::close(_sockfd);
        }
        virtual int Recv(std::string *out)
        {
            //流式读取
            char buffer[1024];
            ssize_t n = ::recv(_sockfd,buffer,sizeof(buffer)-1,0);
            if(n>0)
            {
                buffer[n] = 0;
                *out+=buffer;
            }
           return n;
        }
        virtual int Send(std::string &out)
        {
            return send(_sockfd,out.c_str(),out.size(),0);
        }
        virtual int Connecting(uint16_t port,std::string ip)
        {
            inetaddr server(ip,port);
            return ::connect(_sockfd,server.Netaddrptr(),server.Netaddrlen());
        }
        private:
        int _sockfd;

    };

    class UdpSocket:public Socket
    {

    };
}